今天,我將介紹與 Output
裝飾器 (decorator) 相對應的 output
函數。 output
函數負責向父組件發送值。output
函數傳回一個 OutputEmitterRef
,它有兩個方法:emit
和 subscribe
。儘管 OutputEmitterRef
有 subscribe
方法來使用發出的值,但它與 RxJS
無關。與 @Output
裝飾器 (decorator) 相同, output
函數也有一個別名 (alias) 屬性,可以重新命名自訂事件。
在以下例子中,我展示了 output
如何向父組件傳送值,以及消費者如何使用 subscribe
方法使用傳送的值。
import { Component, ChangeDetectionStrategy, signal, output } from '@angular/core';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-photo-size-output',
standalone: true,
imports: [FormsModule],
template: `
<div style="margin-bottom: 1rem;">
Width: <input type="number" [(ngModel)]="width" />
Height: <input type="number" [(ngModel)]="height" />
<button (click)="size.emit({ width: width(), height: height() })">Change photo</button>
</div>
`,
})
export default class AppPhotoSizeOutputComponent {
width = signal(300);
height = signal(200);
size = output<{
width: number,
height: number,
}>({ alias: 'dimensions'});
}
AppPhotoSizeOutputComponent
的 width
和 height
signals 綁定到 template-driven
表單。當使用者點擊按鈕時,點擊事件會將 width
和 height
物件傳送到 size
output。 size
output 的別名 dimensions
;因此,自訂事件名稱被重新命名為 dimensions
。
import { Component, ChangeDetectionStrategy, input } from '@angular/core';
@Component({
selector: 'app-photo-output',
standalone: true,
template: `
<div class="photo">
<img [src]="img()" alt="Random picture" />
</div>
`,
})
export default class AppPhotoOutputComponent {
img = input.required<string>();
}
AppPhotoOutputComponent
組件具有必需的 img
signal input,用於將圖像 URL 綁定到圖像元素。
import { Component, ChangeDetectionStrategy, signal, output } from '@angular/core';
import AppPhotoOutputComponent from './photo-output.component';
import AppPhotoSizeOutputComponent from './photo-output-size-output.component';
@Component({
selector: 'app-photo-wrapper-output',
standalone: true,
imports: [AppPhotoSizeOutputComponent, AppPhotoOutputComponent],
template: `
<div class="photo-output-wrapper">
<app-photo-size-output (dimensions)="updateSize($event)" />
<app-photo-output [img]="img()" />
</div>
`,
})
export default class AppPhotoWrapperOutputComponent {
img = signal('https://picsum.photos/300/200');
imgUrl = output<string>();
updateSize(result: { width: number; height: number }) {
const { width, height } = result;
const url = `https://picsum.photos/${width}/${height}?random=${Date.now()}`;
this.img.set(url);
this.imgUrl.emit(url);
}
}
AppPhotoWrapperOutputComponent
組件是 AppPhotoSizeOutputComponent
和 AppPhotoOutputComponent
組件的容器。 AppPhotoSizeOutputComponent
組件的自訂 size
事件將值傳送到父組件。 updateSize
方法使用結果建構影像 URL,以 URL 覆寫 img
signal,並將其傳送到 App
組件。 AppPhotoOutputComponent
所需的輸入綁定到 img
signal 以顯示新圖片。
@Component({
selector: 'app-root',
standalone: true,
imports: [AppPhotoWrapperOutputComponent],
template: `
<p>{{ imgUrl() }}</p>
<app-photo-wrapper-output (imgUrl)="imgUrl.set($event)" />
`,
})
export class App {
imgUrl = signal('');
}
AppPhotoWrapperOutputComponent
組件將 imageUrl
傳送到 App 組件,並顯示該值。
subscribe
訂閱 output 值import { Component, signal, output } from '@angular/core';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-photo-size',
standalone: true,
imports: [FormsModule],
template: `
<div style="margin-bottom: 1rem;">
Width: <input type="number" [(ngModel)]="width" />
Height: <input type="number" [(ngModel)]="height" />
<button (click)="size.emit({ width: width(), height: height() })">Change photo</button>
</div>
`,
})
export default class AppPhotoSizeComponent {
width = signal(300);
height = signal(200);
size = output<{
width: number,
height: number,
}>();
}
AppPhotoSizeComponent
具有綁定到範本驅動表單 (template-driven form) 的 width
和 height
signals。當使用者點擊按鈕時,點擊事件會將 width
和 height
物件傳送到 size
output。
import { Component, ChangeDetectionStrategy, signal } from '@angular/core';
@Component({
selector: 'app-photo',
standalone: true,
template: `
<div class="photo">
<img [src]="img()" alt="Random picture" />
</div>
`,
})
export default class AppPhotoComponent {
img = signal('https://picsum.photos/300/200');
}
AppPhotoComponent
組件有一個 img
signal,用於將圖像 URL 綁定到圖像元素。
import { Component, ChangeDetectionStrategy, contentChild, effect } from '@angular/core';
import AppPhotoComponent from './photo.component';
import AppPhotoSizeComponent from './photo-size.componen';
@Component({
selector: 'app-photo-wrapper',
standalone: true,
template: `
<div class="photo-wrapper">
<ng-content />
</div>
`,
})
export default class AppPhotoWrapperComponent {
photo = contentChild.required(AppPhotoComponent);
photoSize = contentChild.required(AppPhotoSizeComponent);
constructor() {
effect(() => {
this.photoSize().size.subscribe(({ width, height }) => {
const url = `https://picsum.photos/${width}/${height}?random=${Date.now()}`;
this.photo().img.set(url);
});
});
}
}
AppPhotoWrapperComponent
組件使用 contentChild
函數來查詢 AppPhotoComponent
和 AppPhotoSizeComponent
組件。 AppPhotoWrapperComponent
組件訂閱 AppPhotoSizeComponent
組件的 size
output。當 size
output 發出父級的值時, subscribe
方法會建構圖片 URL 並設定 AppPhotoComponent
組件的 img
signal。signal
接收新值,AppPhotoComponent
組件顯示新圖片。
<h3>Subscribe output function</h3>
<app-photo-wrapper>
<app-photo-size />
<app-photo style="margin-bottom: 1rem;" />
</app-photo-wrapper>
在 App
組件中,AppPhotoSizeComponent
和 AppPhotoComponent
組件被投影到 AppPhotoWrapperComponent
,以便 contentChild
函數可以查詢它們,並且可以透過 subscribe
訂閱 the size
output。
output
函數允許元件向父組件發出值。output
函數傳回具有 emit
和 subscrib
e 方法的 OutputEmitterRef
。 emit
方法將值傳送給父元件。 subscribe
方法以程式設計方式使用發出的值。output
函數接受帶有別名屬性的選項物件。內部 output
名稱可以與組件層級的事件名稱不同。outputToObservable
將輸出轉換為 Observable
。 outputFromObservable
從 Observable
轉換為輸出。 這些功能可以在 rxjs-interop
套件中找到。鐵人賽的第 23 天到此結束。